﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using WebUtility;


namespace MvcHtmlHelpers
{
    public static class HtmlHelperDataGridEx
    {

       public static MvcHtmlString DataGrid<T> (this HtmlHelper helper, object data, ColumnDescriptor columns = null, string gridID = null,bool hasOrdinalNo = true,string sortCol = null,bool? isAsc = true)
       {
           //get items
           var items = data  as IEnumerable<T>;

           //get columns name
           if(columns == null)
           {
                List<string> columnNames = typeof (T).GetProperties().Select(p => p.Name).ToList();
               columns  = new ColumnDescriptor();
               columnNames.ForEach(x=> columns.Add(new Column() { PropertyName = x, HeaderText = x }));
           }

           //create htmlTextWriter
           var writer = new HtmlTextWriter(new StringWriter());

           //open table tag
           if (!string.IsNullOrEmpty(gridID))
           {
               writer.AddAttribute(HtmlTextWriterAttribute.Id, gridID);
           }
           writer.AddAttribute(HtmlTextWriterAttribute.Class, "grid");
           writer.RenderBeginTag(HtmlTextWriterTag.Table);
           
           //render table header
           writer.RenderBeginTag(HtmlTextWriterTag.Thead);
           RenderHeader(helper, writer, columns,hasOrdinalNo,sortCol,isAsc);
           writer.RenderEndTag();

           //render table body
           writer.RenderBeginTag(HtmlTextWriterTag.Tbody);
           if(items != null)
           {
               for (int i = 0; i < items.Count(); i++)
               {
                   RenderRow<T>(helper, writer, columns, items.ElementAt(i), hasOrdinalNo, i + 1);
               }
           }
        
         
           writer.RenderEndTag();

           writer.RenderEndTag();

           return new MvcHtmlString(writer.InnerWriter.ToString());


       }

       private static void RenderRow<T>(HtmlHelper helper, HtmlTextWriter writer, ColumnDescriptor columns, object item, bool hasOrdinalNo, int ordNo)
       {
           writer.RenderBeginTag(HtmlTextWriterTag.Tr);
           if(hasOrdinalNo)
           {
               writer.RenderBeginTag(HtmlTextWriterTag.Td);
               writer.Write(helper.Encode(ordNo.ToString()));
               writer.RenderEndTag();
           }
           foreach (var col in columns)
           {
               writer.RenderBeginTag(HtmlTextWriterTag.Td);
               var value = typeof (T).GetProperty(col.PropertyName).GetValue(item, null) ?? String.Empty;
               writer.Write(helper.Encode(value.ToString()));
               writer.RenderEndTag();
           }
           writer.RenderEndTag();
       }

       private static void RenderHeader(HtmlHelper helper, HtmlTextWriter writer, ICollection<Column> columns, bool hasOrdNo, string sortCol, bool? isAsc)
       {
           writer.RenderBeginTag(HtmlTextWriterTag.Tr);
           if(hasOrdNo)
           {
               writer.RenderBeginTag(HtmlTextWriterTag.Th);
               writer.WriteEncodedText("No.");
               writer.RenderEndTag();
           }
          
           foreach (var col in columns)
           {

               writer.RenderBeginTag(HtmlTextWriterTag.Th);

               if(col.Sortable)
               {
                   var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
                   var link = helper.ActionLink(col.HeaderText, currentAction, new { sort = col.PropertyName, ord = isAsc.HasValue ? isAsc.Value ? "desc" : "asc" : "desc" });
                   writer.Write(link);
                   if (sortCol == col.PropertyName)
                   {
                       writer.AddAttribute(HtmlTextWriterAttribute.Class, isAsc.HasValue ? isAsc.Value ? "asc" : "desc" : "asc");
                       writer.RenderBeginTag(HtmlTextWriterTag.Div);
                       writer.Write(" ");
                       writer.RenderEndTag();
                   }
               }else
               {
                   writer.RenderBeginTag(HtmlTextWriterTag.Span);
                   writer.Write(col.HeaderText);
                   writer.RenderEndTag();
               }
               writer.RenderEndTag();
           }
           writer.RenderEndTag();
       }
    }
}
